/*
 * TOP SECRET Copyright 2006-2015 Transsion.com All right reserved. This software is the confidential and proprietary
 * information of Transsion.com ("Confidential Information"). You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license agreement you entered into with Transsion.com.
 */
package com.yunji.framework_template.orm.datasource.sharding;

import java.util.Collection;
import java.util.LinkedHashSet;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;

import com.yunji.framework_template.common.constant.Constant;
import com.yunji.framework_template.common.util.NumberUtil;

/**
 * 对表进行分片的算法，其中只使用IMEI这一个字段。该算法的根据IMEI的TAC（前6位）进行分片，将结果分到两个不同的数据库中。 <br>
 * ClassName:IMEISingleKeyDatabaseShardingAlgorithm <br/>
 * Date: 2017年8月17日 上午9:31:26 <br/>
 * 
 * @author fenglibin
 * @version
 * @see
 */
public class IMEISingleKeyDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<String> {

    /**
     * 分庫的数量
     */
    private static final int    SHARDING_DATABASES      = 2;
    /**
     * 第一个庫
     */
    private static final String FIRST_SHARDING_DATABASE = "1";
    /**
     * 标准IMEI的长度
     */
    private static final int    IMEI_LENGTH             = 15;
    private static final int    TAC_START_POSITION      = 0;
    private static final int    TAC_END_POSITION        = 6;

    @Override
    public String doEqualSharding(Collection<String> dataSourceNames, ShardingValue<String> shardingValue) {
        /**
         * 通过IMEI进行分片，IMEI共由15位组成，其组成为: <br>
         * 1、前6位数(TAC)是"型号核准号码"，一般代表机型。 <br>
         * 2、接着的2位数(FAC)是"最后装配号"，一般代表产地。<br>
         * 3、之后的6位数(SNR)是"串号"，一般代表生产顺序号。 <br>
         * 4、最后1位数(SP)通常是"0"，为检验码，目前暂备用。 <br>
         * 这里取SNR号作为分表的依据，即取9位到第14位6个数字作为计算基数。该算法共分
         */
        String currentShardingTable = Constant.EMPTY_STRING;
        String imei = shardingValue.getValue();
        if (!NumberUtil.isNumber(imei)) {// 如果是非数字的（人为测试的情况下可能出现这种），就分配第一个庫
            currentShardingTable = FIRST_SHARDING_DATABASE;
        }
        if (imei.length() != IMEI_LENGTH) {// 如果是长度不是15的数字，则将整个数据与分庫数进行求余
            currentShardingTable = String.valueOf(Long.parseLong(imei) % SHARDING_DATABASES);
        }

        if (Constant.EMPTY_STRING.equals(currentShardingTable)) {
            // 取设备的6位TAC
            currentShardingTable = String.valueOf(Integer.parseInt(imei.substring(TAC_START_POSITION, TAC_END_POSITION))
                                                  % SHARDING_DATABASES);
        }
        for (String each : dataSourceNames) {
            if (each.endsWith(currentShardingTable)) {
                return each;
            }
        }
        throw new IllegalArgumentException("Cannot identify sharding database by imei:" + imei
                                           + " in equals sharding.");
    }

    @Override
    public Collection<String> doInSharding(Collection<String> dataSourceNames, ShardingValue<String> shardingValue) {
        Collection<String> result = new LinkedHashSet<String>(dataSourceNames.size());
        for (String value : shardingValue.getValues()) {
            result.add(doEqualSharding(dataSourceNames,
                                       new ShardingValue<String>(shardingValue.getLogicTableName(),
                                                                 shardingValue.getColumnName(), value)));
        }
        return result;
    }

    @Override
    public Collection<String> doBetweenSharding(Collection<String> dataSourceNames,
                                                ShardingValue<String> shardingValue) {
        /**
         * imei不存根据范围即sql中的between这种作为条件进行查询的，因而该方法不需要实现
         */
        return null;
    }

}
